package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.sun.org.apache.regexp.internal.RE;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.db.api.FreezeApi;
import com.tanhua.dubbo.db.api.UserInfoApi;
import com.tanhua.dubbo.mongo.api.CommentApi;
import com.tanhua.dubbo.mongo.api.MovementApi;
import com.tanhua.dubbo.mongo.api.RecommendUserApi;
import com.tanhua.dubbo.mongo.api.VisitorsApi;
import com.tanhua.model.db.Freeze;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private CommentApi commentApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private FreezeApi freezeApi;

    @Autowired
    private MqMessageService mqMessageService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    //动态-取消点赞 并返回动态的总点赞数
    public Integer dislike(String movementId) {

        //获取点赞者id
        Long userId = UserHolder.getUserId();

        //设定commentType,点赞-->1
        int commentType = 1;

        //先查询该条动态"我"是否有点赞,返回值布尔
        Boolean hasComment = commentApi.hasComment(movementId, userId, commentType);

        if (!hasComment) { //若未点赞 返回错误信息
            throw new BusinessException(ErrorResult.disLikeError());
        }

        //点赞状态 则取消点赞 从mongDB数据库中删除
        Integer count = commentApi.dislike(movementId, userId, commentType);

        //从redis中删除
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(key, hashKey);


        return count;
    }


    //动态-点赞并返回动态的总点赞数
    public Integer like(String movementId) {

        //获得点赞者的userId
        Long userId = UserHolder.getUserId();

        //设定commentType,点赞-->1
        int commentType = 1;

        //先查询该条动态"我"是否有点赞,返回值布尔
        Boolean hasComment = commentApi.hasComment(movementId, userId, commentType);

        if (hasComment) {
            // 如果已点赞,返回错误信息
            ErrorResult result = ErrorResult.likeError();
            throw new BusinessException(result);
        }

        //将点赞数据保存到mongoDB中
        Comment comment = new Comment();

        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(commentType);
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());

        Integer count = commentApi.saveComment(comment);

        //保存到redis中
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().put(key, hashKey, "1");

        return count;
    }


    //动态-发布
    public void movements(String textContent, MultipartFile[] imageContent) throws IOException {
        Long userId = UserHolder.getUserId();

        //查询该用户否被冻结
        String key = Constants.USER_FREEZE+userId;
        Freeze freeze = freezeApi.findFreezeByUserId(userId);
        if (freeze != null) {
            UserInfo userInfo = userInfoApi.findById(userId);
            //获取从redis中获取的数据
            String freezeTime = redisTemplate.opsForValue().get(key);
            Integer freezingTime = freeze.getFreezingTime();
            if (freezeTime == null && freezingTime != 3) {
                userInfo.setUserStatus("1");
                userInfoApi.updateUserInfo(userInfo);
            }
            if (freezeTime != null) {
                if (userInfo.getUserStatus().equals("2") && freeze.getFreezingRange() == 3) {
                    throw new BusinessException(ErrorResult.freezeCommentError());
                }
            }
        }

        //将传过来的图片上传到阿里云 获得图片链接
        List<String> url = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            url.add(upload);
        }

        //构建Movements对象
        Movement movement = new Movement();
        movement.setUserId(userId);
        movement.setCreated(System.currentTimeMillis());
        movement.setTextContent(textContent);
        movement.setMedias(url);

        //调用api保存
        String movementId=movementApi.save(movement);

        //发送消息
        mqMessageService.sendAudiService(movementId);

    }

    //查询我的动态
    public PageResult findByUserId(Integer page, Integer pagesize, Long userId) {

        //根据userId查询动态表中的数据
        List<Movement> movements = movementApi.findById(page, pagesize, userId);

        //判断movements是否存在
        if (movements == null || movements.size() <= 0) {
            //不存在 返回一个空的PageResult对象
            return new PageResult();
        }

        //根据userId查询userInfo的数据
        UserInfo userInfo = userInfoApi.findById(userId);

        //PageResult里要封装的对象list集合
        List<MovementsVo> vos = new ArrayList<>();

        //循环movements
        for (Movement movement : movements) {
            //根据userInfo和movement获得每一个MovementsVo对象
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //存入vosList中
            vos.add(vo);
        }
        //返回
        return new PageResult(page, pagesize, 0l, vos);
    }


    //查询好友动态
    public PageResult findByFriendId(Integer page, Integer pagesize) {

        //获得登录者的userId,即可见人id
        Long friendId = UserHolder.getUserId();

        //根据可见人id 获取动态表数据
        List<Movement> movements = movementApi.findByFriendId(page, pagesize, friendId);

        return getPageResult(movements, page, pagesize);
    }

    //查询推荐动态
    public PageResult findByRecommend(Integer page, Integer pagesize) {

        //获得当前登录用户的userId
        Long userId = UserHolder.getUserId();

        String value = redisTemplate.opsForValue().get("MOVEMENTS_RECOMMEND_" + userId);

        List<Movement> movements = new ArrayList<>();
        //判断value是否存在
        if (StringUtils.isEmpty(value)) {
            // 当从redis中获得的value==null,构建假数据返回
            movements = movementApi.findRandom(pagesize);
        } else {
            //value存在时,根据redis中取得MovementId查询数据并返回
            String[] movementIds = value.split(",");
            movements = movementApi.findByMovementIds(page, pagesize, movementIds);
        }


        ////返回
        return getPageResult(movements, page, pagesize);
    }


    //根据动态表的id查询单条动态
    public MovementsVo findByMovementId(String id) {


        Movement movement = movementApi.findByMovementId(id);

        UserInfo userInfo = userInfoApi.findById(movement.getUserId());

        MovementsVo vo = MovementsVo.init(userInfo, movement);

        RecommendUser re = recommendUserApi.queryByUserId(userInfo.getId(), UserHolder.getUserId());

        //将我访问佳人的信息 添加到visitors表中
        //创建对象
        Visitors visitors=new Visitors();
        visitors.setUserId(userInfo.getId());
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyMMdd").format(new Date()));
        visitors.setFrom("圈子");
        visitors.setScore(re.getScore());
        visitorsApi.save(visitors);

        return vo;
    }


    //返回PageResult的方法
    public PageResult getPageResult(List<Movement> movements, Integer page, Integer pagesize) {
        //判断movements是否存在
        if (movements == null || movements.size() <= 0) {
            //不存在 返回一个空的PageResult对象
            return new PageResult();
        }

        //根据工具类获得所有动态发布者的userId
        List<Long> ids = CollUtil.getFieldValues(movements, "userId", Long.class);

        //根据ids 获得 UserInfo的Map集合
        Map<Long, UserInfo> infoMap = userInfoApi.findByIds(ids);

        //MovementsVo的list集合
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : movements) {
            //一个Movement 对应一个UserInfo
            UserInfo userInfo = infoMap.get(movement.getUserId());
            //vo存入vos
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //从redis中查询数据是否存在
            String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();

            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hashLike = redisTemplate.opsForHash().hasKey(key, hashKey);
            if (hashLike){
                vo.setHasLiked(1);
            }

            //从redis中查询数据是否存在
            String hashKey2=Constants.MOVEMENT_LOVE_HASHKEY+UserHolder.getUserId();
            Boolean hashLove = redisTemplate.opsForHash().hasKey(key, hashKey2);
            if (hashLove){
                vo.setHasLoved(1);
            }
            vos.add(vo);

        }
        return new PageResult(page, pagesize, 0l, vos);
    }


    //谁看过我 查询访问者：
    public List<TodayBest> visitors() {

        //根据时间段查询 (已看过的数据不再显示) ,获取上一次观看的时间
        String key=Constants.VISITORS_USER+UserHolder.getUserId();
        String time = redisTemplate.opsForValue().get(key);
        Long date=0l;
        if (!StringUtils.isEmpty(time)){
            date = Long.valueOf(time);
        }

        //根据本人id查询userId
        List<Visitors> list= visitorsApi.findById(UserHolder.getUserId(),date);

        //判断
        if (list==null || list.size()<=0){
            return new ArrayList<>();
        }

        //根据userId查询UserInfo
        List<Long> ids = CollUtil.getFieldValues(list, "visitorUserId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids);

        List<TodayBest> vos=new ArrayList<>();
        //一个userInfo 构建一个TodayBest

        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());

            TodayBest vo = TodayBest.init(userInfo, visitors);
            vos.add(vo);
        }

        return vos;
    }

    //动态-喜欢 并返回喜欢总数
    public Integer love(String movementId) {
        //获得本人id
        Long userId = UserHolder.getUserId();
        int commentType=3; //喜欢
        //查询该动态我是否喜欢 ，若已喜欢 返回错误信息
        Boolean hasComment = commentApi.hasComment(movementId, userId, commentType);

        if (hasComment){
            throw  new BusinessException(ErrorResult.loveError());
        }


        //创建comment表对象,保存到mongoDB中
       Comment comment=new Comment();
       comment.setCommentType(commentType);
       comment.setPublishId(new ObjectId(movementId));
       comment.setUserId(userId);
       comment.setCreated(System.currentTimeMillis());
       Integer count = commentApi.saveComment(comment);

       //存入redis中
        String key=Constants.MOVEMENTS_INTERACT_KEY+movementId;
        String hashKey=Constants.MOVEMENT_LOVE_HASHKEY+userId;
        redisTemplate.opsForHash().put(key,hashKey,"1");

        return count;
    }


    //动态-取消喜欢 ,并返回喜欢总数
    public Integer unlove(String movementId) {

        //获得登录着的userId
        Long userId = UserHolder.getUserId();
        int commentType=3; //喜欢

        //判断是否存在该条喜欢数据,不存在返回错误信息
        Boolean hasComment = commentApi.hasComment(movementId, userId, commentType);

        if (!hasComment){
            throw  new BusinessException(ErrorResult.disloveError());
        }

      Integer count=  commentApi.dislike(movementId,userId,commentType);

        //从redis中删除
        String key=Constants.MOVEMENTS_INTERACT_KEY+movementId;
        String hashKey=Constants.MOVEMENT_LOVE_HASHKEY+userId;
        redisTemplate.opsForHash().delete(key,hashKey);

        return count;
    }
}
